<?php

require_once INTE_ROOT . 'IUser.php';
require_once CONF_ROOT . 'UserConf.php';
require_once CONF_ROOT . 'BaseConf.php';
require_once DATA_ROOT . 'UserData.php';
require_once DATA_ROOT . 'UserRelationData.php';
require_once DATA_ROOT . 'VerifyData.php';
require_once DEF_ROOT . 'UserDef.php';
require_once DEF_ROOT . 'NotifyDef.php';
require_once LOGIC_ROOT . 'BaseNotify.php';
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

class BaseUser implements IUser {

    public static function getInstance() {
        if (self::$instance == null) {
            self::$instance = new BaseUser();
        }
        return self::$instance;
    }

    protected static $instance = null;

    protected function __construct() {
        
    }

    /*
     * 根据uid返回用户信息
     */

    public function getUserByUid($uid) {
        $ret = array('err' => ErrorDef::OK);
        $arr_cond = array('uid' => $uid);
        $arr_ne_cond = array('status' => UserStatus::DELETED);
        $res = UserData::model()->getData(null, $arr_cond, $arr_ne_cond);
        if (ErrorDef::OK == $res['err']) {
            if (!empty($res['data'])) {
                $ret['data'] = $res['data'][0];
            } else {
                $ret['err'] = ErrorDef::COMMON_ERROR_NOT_EXIST;
            }
        }
        return $ret;
    }

    /*
     * 
     */

    public function getUserByUname($uname) {
        $arr_cond = array('uname' => $uname);
        $arr_ne_cond = array('status' => UserStatus::DELETED);
        $userData = UserData::model()->getData(null, $arr_cond, $arr_ne_cond);
        if (ErrorDef::OK == $userData['err'] && empty($userData['data'])) {
            $userData['err'] = ErrorDef::COMMON_ERROR_NOT_EXIST;
        }
        return $userData;
    }

    /*
     *
     */

    public function getUserByEmail($email) {
        $ret = array('err' => ErrorDef::OK);
        $arr_cond = array('email' => $email);
        $arr_ne_cond = array('status' => UserStatus::DELETED);
        $res = UserData::model()->getData(null, $arr_cond, $arr_ne_cond);
        if (ErrorDef::OK == $res['err']) {
            if (!empty($res['data'])) {
                $ret['data'] = $res['data'][0];
            } else {
                $ret['err'] = ErrorDef::COMMON_ERROR_NOT_EXIST;
            }
        }
        return $ret;
    }

    // FIXME： 最好联表，不然数据不稳定
    /*
     * 根据uid返回关注该id的人
     */
    public function getFollowers($uid, $pnum, $psize) {
        $ret = array('err' => ErrorDef::OK, 'data' => array());
        try {
            $data = array();
            $conds = array('uid2' => $uid, 'status' => UserRelationStatus::NORMAL);
            $userRelations = UserRelationData::model()->findData(array('uid1'), $conds, null, null, 'create_time', false, $pnum * $psize, $psize, $count);

            // 抽取uid:
            $uids = array();
            foreach ($userRelations as $userRelation) {
                $uids[] = $userRelation->uid1;
            }
            $arr_userDatas = array();
            if (!empty($uids))
            {
                $arr_userDatas = $this->getUserByUids($uids);
            }
            $ret['data'] = $arr_userDatas;
            $ret['tn'] = $count;
            $ret['pn'] = $pnum;
            $ret['ps'] = count($arr_userDatas);
        } catch (Exception $e) {
            $err_code = $e->getCode();
            if (empty($err_code)) {
                $ret['err'] = ErrorDef::COMMON_ERROR_SYS;
            } else {
                $ret['err'] = $err_code;
            }
        }
        return $ret;
    }

    /*
     * 根据uid返回该id关注的人
     */

    public function getFolloweds($uid, $pnum, $psize) {
        $ret = array('err' => ErrorDef::OK, 'data' => array());
        try {
            $conds = array('uid1' => $uid, 'status' => UserRelationStatus::NORMAL);
            $userRelations = UserRelationData::model()->findData(array('uid2'), $conds, null, null, 'create_time', false, $pnum * $psize, $psize, $count);

            // 抽取uid:
            $uids = array();
            foreach ($userRelations as $userRelation) {
                $uids[] = $userRelation->uid1;
            }
            $arr_userDatas = array();
            if (!empty($uids))
            {
                $arr_userDatas = $this->getUserByUids($uids);
            }
            $arr_userDatas = $this->getUserByUids($uids);
            $ret['data'] = $arr_userDatas;
            $ret['tn'] = $count;
            $ret['pn'] = $pnum;
            $ret['ps'] = count($arr_userDatas);
        } catch (Exception $e) {
            $err_code = $e->getCode();
            if (empty($err_code)) {
                $ret['err'] = ErrorDef::COMMON_ERROR_SYS;
            } else {
                $ret['err'] = $err_code;
            }
        }
        return $ret;
    }

    /*
     *
     */

    public function addUser($userData) {
        $ret = array('err' => ErrorDef::OK);

        try {
            if ($userData->isIllegalInAdd()) {
                throw new Exception('the user info is invalid.[' . print_r($userData, true) . ']', ErrorDef::COMMON_ERROR_PARAM);
            }
            $userData->initUser();
            $arr_cond = array('email' => $userData->email);
            $user = UserData::model()->getData(null, $arr_cond);
            if (!empty($user['data'])) {
                if (!empty($user['data'][0]) && UserStatus::DELETED == $user['data'][0]->status) {
                    // 虽然存在但是已经被删除，直接恢复
                    $res = $userData->recoverUser($user['data'][0]);
                    if (false === $res) {
                        throw new Exception('failed in update user[' . $userData->email . '] with uid[' . $userData->uid . ']');
                    }
                } else {
                    throw new Exception('the user[' . $userData->email . '] is exist with uid[' . $userData->uid . ']', ErrorDef::COMMON_ERROR_EXIST);
                }
            } else {
                // 用户不存在，新建一个
                $res = $userData->save();
                if (false === $res) {
                    throw new Exception('failed in insert user[' . $userData->email . ']');
                }
            }
            $ret['data'] = $userData;
            if (ErrorDef::OK == $ret['err']) {
                // 创建用户成功，生成认证码
                $code_str = $userData->last_modify_time . rand(0, BaseConf::RAND_MAX);
                $encode_str = base64_encode($userData->email . BaseConf::DELIMETER . $code_str);
                $ret['encode'] = $encode_str;
                VerifyData::genRecord($userData->uid, $code_str);
            }
        } catch (Exception $e) {
            $err_code = $e->getCode();
            if (empty($err_code)) {
                $ret['err'] = ErrorDef::COMMON_ERROR_SYS;
            } else {
                $ret['err'] = $err_code;
            }
        }
        return $ret;
    }

    /*
     *
     */

    public function editUser($userData) {
        $ret = array('err' => ErrorDef::OK);
        try {
            if ($userData->isIllegalInEdit()) {
                throw new Exception('the user info is invalid.[' . print_r($userData, true) . ']', ErrorDef::COMMON_ERROR_PARAM);
            }

            // 找到要更新的用户，确认存在
            $uid = $userData->uid;
            $arr_cond = array('uid' => $uid);
            $arr_ne_cond = array('status' => UserStatus::DELETED);
            $res = UserData::model()->findData(null, $arr_cond, $arr_ne_cond);
            if (empty($res)) {
                throw new Exception('the user[' . $uid . '] is not exist in user table', ErrorDef::COMMON_ERROR_NOT_EXIST);
            }
            $userData_old = $res[0];
            $userData_old->editData($userData);
        } catch (Exception $e) {
            $err_code = $e->getCode();
            if (empty($err_code)) {
                $ret['err'] = ErrorDef::COMMON_ERROR_SYS;
            } else {
                $ret['err'] = $err_code;
            }
        }
        return $ret;
    }

    /*
     *
     */

    public function followUser($uid_follow, $uid_followed) {
        $ret = array('err' => ErrorDef::OK);
        try {
            // 确认用户存在
            $cond = array('uid' => $uid_follow);
            $arr_ne_cond = array('status' => UserStatus::DELETED);

            $res = UserData::model()->findData(null, $cond, $arr_ne_cond);
            if (empty($res)) {
                throw new Exception('the user for uid follow[' . $uid_follow . '] is not exist', ErrorDef::COMMON_ERROR_NOT_EXIST);
            }
            $user_follow = $res[0];

            $cond = array('uid' => $uid_followed);
            $res = UserData::model()->findData(null, $cond, $arr_ne_cond);
            if (empty($res)) {
                throw new Exception('the user for uid followed[' . $uid_followed . '] is not exist', ErrorDef::COMMON_ERROR_NOT_EXIST);
            }
            $user_followed = $res[0];

            $cond = array('uid1' => $uid_follow, 'uid2' => $uid_followed);
            $res = UserRelationData::model()->findData(null, $cond);

            if (!empty($res)) {
                // 已存在
                if (isset($res[0]) && UserRelationStatus::DELETED == $res[0]->status) {
                    $userRelation->updateStatus(UserRelationStatus::NORMAL);
                } else {
                    throw new Exception('the user relation with uid1[' . $uid_follow . '], uid2[' . $uid_followed . '] is exist', ErrorDef::COMMON_ERROR_EXIST);
                }
            } else {
                UserRelationData::genUserRelation($uid_follow, $uid_followed);
                if ($user_followed->status & NoticeConfig::BE_FOLLOWED > 0) {
                    BaseNotify::getInstance()->addNotify($uid_followed, NotifyType::NEW_FOLLOWER);
                }
            }
        } catch (Exception $e) {
            $err_code = $e->getCode();
            if (empty($err_code)) {
                $ret['err'] = ErrorDef::COMMON_ERROR_SYS;
            } else {
                $ret['err'] = $err_code;
            }
        }
    }

    /*
     *
     */

    public function unFollowUser($uid_follow, $uid_followed) {
        $ret = array('err' => ErrorDef::OK);
        try {
            $cond = array('uid1' => $uid_follow, 'uid2' => $uid_followed);
            $res = UserRelationData::model()->findData(null, $cond);
            if (!empty($res)) {
                $userRelation = $res[0];
                $userRelation->updateStatus(UserRelationStatus::DELETED);
            }
        } catch (Exception $e) {
            $err_code = $e->getCode();
            if (empty($err_code)) {
                $ret['err'] = ErrorDef::COMMON_ERROR_SYS;
            } else {
                $ret['err'] = $err_code;
            }
        }
        return $ret;
    }

    /*
     * 
     */

    public function checkPwd($email, $pwd) {
        $ret = array('err' => ErrorDef::OK);
        try {
            $arr_cond = array('email' => $email);
            $arr_ne_cond = array('status' => UserStatus::DELETED);
            $res = UserData::model()->findData(null, $arr_cond, $arr_ne_cond);
            if (empty($res)) {
                throw new Exception('the user[' . $email . '] is not exist in user table', ErrorDef::COMMON_ERROR_NOT_EXIST);
            }
            $userData = $res[0];
            $pwd_encoded = UserData::encodePassword($pwd);
            if ($userData->password != $pwd_encoded) {
                throw new Exception('error in checking password for user[' . $email . '] with password[' . $pwd . ']', ErrorDef::USER_ERROR_PWD);
            }
            $userData->last_login_time = time();
            $userData->updateDatas(array('last_login_time'));
            $ret['data'] = $userData;
        } catch (Exception $e) {
            $err_code = $e->getCode();
            if (empty($err_code)) {
                $ret['err'] = ErrorDef::COMMON_ERROR_SYS;
            } else {
                $ret['err'] = $err_code;
            }
            echo $e->getMessage();
        }
        return $ret;
    }

    public function verifyUser($str_encode) {
        $ret = array('err' => ErrorDef::OK);

        try {
            if (empty($str_encode)) {
                throw new Exception('the encode string can not be null', ErrorDef::COMMON_ERROR_PARAM);
            }
            // 解码
            $str_decode = base64_decode($str_encode);
            if (empty($str_decode)) {
                throw new Exception('failed to decoce string[' . $str_encode . ']', ErrorDef::VERIFY_ERROR_CODE);
            }

            $decode_parts = explode(BaseConf::DELIMETER, $str_decode);
            if (!isset($decode_parts[1]) || count($decode_parts) > 2 || strlen($decode_parts[1] <= 10)) {
                throw new Exception('the format of decoded string[' . $str_decode . '] is invalid', ErrorDef::VERIFY_ERROR_CODE);
            }

            $str_decode = $decode_parts[1];
            $email = $decode_parts[0];
            // 判断用户是否已经被验证
            $arr_cond = array('email' => $email, 'status' => UserStatus::INIT);
            $res = UserData::model()->findData(null, $arr_cond);
            if (empty($res)) {
                throw new Exception('the user[' . $email . '] is not exist in user table', ErrorDef::COMMON_ERROR_NOT_EXIST);
            }
            $userData = $res[0];

            $uid = $userData->uid;
            $res = VerifyData::model()->findData(null, array('uid' => $uid));
            if (empty($res)) {
                throw new Exception('the verify data for user[' . $uid . '] is not exist in user relation table', ErrorDef::COMMON_ERROR_NOT_EXIST);
            }
            $verifyData = $res[0];

            if ($verifyData->code == $str_decode) {
                $userData->updateStatus(UserStatus::NORMAL);
                $verifyData->updateFlag(VerifyStatus::VERIFIED);
                $ret['err'] = ErrorDef::OK;
            } else {
                throw new Exception('error in verify user[' . $email . '] with encode[' . $str_encode . '] or decode[' . $str_decode . ']', ErrorDef::VERIFY_ERROR_CODE);
            }
        } catch (Exception $e) {
            $err_code = $e->getCode();
            if (empty($err_code)) {
                $ret['err'] = ErrorDef::COMMON_ERROR_SYS;
            } else {
                $ret['err'] = $err_code;
            }
            echo $e->getMessage();
        }
        return $ret;
    }

    protected function getUserByUids($uids) {
        $chunked_uids = array_chunk($uids, BaseConf::COUNTS_PER_QUERY);
        $arr_userDatas = array();
        foreach ($chunked_uids as $uids) {
            $arr_cond_in = array('uid' => $uids);
            $arr_ne_cond = array('status' => UserStatus::DELETED);
            $userDatas = UserData::model()->findData(null, null, $arr_ne_cond, $arr_cond_in);
            $arr_userDatas = array_merge($userDatas, $arr_userDatas);
        }
        return $arr_userDatas;
    }

}
